#include "StdAfx.h"

#include "umc_defs.h"
#if defined (UMC_ENABLE_H264_SPLITTER)
#include "CoshipH264Splitter.h"
#include "H264FrameReader.h"

CoshipH264Splitter::CoshipH264Splitter()
:m_streamNALUUnlocked(false)
{
	m_bEndOfSourceSeen = false;
	m_bEndOfAUSeen = false;
}

CoshipH264Splitter::~CoshipH264Splitter()
{
	Close();
}

void CoshipH264Splitter::Init()
{
	m_bEndOfSourceSeen = false;
	m_bEndOfAUSeen = false;
	m_dataFile.SetBufferPointer(0, 0);
	m_dataFile.SetDataSize(0);
	m_streamAU.Init();
	m_streamNALU.Init();
}

Status CoshipH264Splitter::Init(SplitterParams &initParams)
{
	// check incompatible flag(s)
	if (0 == (initParams.m_lFlags & VIDEO_SPLITTER))
		return UMC_ERR_INVALID_STREAM;

	// check parameter(s)
	if (NULL == initParams.m_pDataReader)
		return UMC_ERR_NULL_PTR;

	Close();
	Init();

	m_pDataReader = initParams.m_pDataReader;

	return UMC_OK;
}

Status CoshipH264Splitter::Close()
{
	m_pDataReader = 0;
	return UMC_OK;
}

Status CoshipH264Splitter::LoadByteData(MediaData & p_data)
{
	Ipp32u iRead = sizeof(m_aFileBuffer);
	Status umsRes = m_pDataReader->ReadData(m_aFileBuffer, &iRead);
	p_data.SetBufferPointer(m_aFileBuffer, iRead);
	p_data.SetDataSize(iRead);
	if (umsRes != UMC_OK && !iRead)
	{
		return UMC_ERR_NOT_ENOUGH_DATA;
	}
	return UMC_OK;
}

Status CoshipH264Splitter::GetNALUData(MediaData & p_data)
{
	if(m_bEndOfSourceSeen)
	{
		return UMC_ERR_END_OF_STREAM;
	}

	if (!m_streamNALUUnlocked)
	{
		m_streamNALU.UnLockOutputData();
		m_streamNALUUnlocked = true;
	}

	for(;;)
	{
		if(!m_bEndOfSourceSeen){
			if(m_dataFile.GetDataSize() == 0){
				if( UMC_OK != LoadByteData(m_dataFile)){
					return UMC_ERR_NOT_ENOUGH_DATA;
					//m_bEndOfSourceSeen = true;
					//m_streamNALU.LockOutputData(p_data);
					//return p_data.GetDataSize() == 0 ? UMC_ERR_NOT_ENOUGH_DATA : UMC_OK;
				}
			}
		}

		Status status = m_streamNALU.PutData(m_dataFile);
		if( UMC_OK == status )
		{
			m_streamNALU.LockOutputData(p_data);
			m_streamNALUUnlocked = false;
			return status;
		} else if( UMC_ERR_NOT_ENOUGH_DATA == status){
			return UMC_ERR_NOT_ENOUGH_DATA;
		} else {
			// Error or other event seen
			return status;
		}
	}
}

bool CoshipH264Splitter::HasMoreBinData()
{
	return m_dataFile.GetDataSize() > 0 ? true : false;
}

Status CoshipH264Splitter::GetNextData(MediaData *pFrame, Ipp32u )
{
	H264FrameReader *rdr = (H264FrameReader *) m_pDataReader;
	if (m_dataFile.GetDataSize() == 0 && rdr->GetRemainDataSize() == 0)
		return UMC_ERR_NOT_ENOUGH_DATA;

	if(m_bEndOfAUSeen){
		pFrame->SetBufferPointer(0, 0);
		pFrame->SetDataSize(0);
		return UMC_ERR_END_OF_STREAM;
	}

	for(;;)
	{
		MediaData dataNALU;
		Status status = GetNALUData(dataNALU);
		if(UMC_OK == status){
			Status statusAU = m_streamAU.PutData(dataNALU);
			if(UMC_OK == statusAU){
				m_streamAU.LockOutputData(*pFrame);
				return UMC_OK;
			}
		} else {
			return UMC_ERR_NOT_ENOUGH_DATA;
			//m_streamAU.Swap();
			//m_streamAU.LockOutputData(*pFrame);
			////m_bEndOfAUSeen = true;
			//return pFrame->GetDataSize() == 0 ? UMC_ERR_END_OF_STREAM : UMC_OK;
		}
	}
}

#endif // UMC_ENABLE_H264_SPLITTER
